/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package QASystem;

import DCGTree.Node;
import DCGTree.Parser;
import GraphViz.GraphViz;
import Tokenizer.Token;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.xml.parsers.ParserConfigurationException;
import jpl.JPL;
import jpl.JPLException;
import jpl.Query;
import org.xml.sax.SAXException;
import java.util.regex.*;

/**
 *
 * @author Raito
 */
public class QAProvider {

    private static List<String> LoadConfig() throws SAXException {
        try {
            List<String> valueOfSyntax = new ArrayList<String>();
            valueOfSyntax = Config.getAllSyntaxFiles();
            return valueOfSyntax;
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(QASystem.class.getName()).log(Level.SEVERE, null, ex.getMessage());
        } catch (SAXException ex) {
            Logger.getLogger(QASystem.class.getName()).log(Level.SEVERE, null, ex.getMessage());
        } catch (IOException ex) {
            Logger.getLogger(QASystem.class.getName()).log(Level.SEVERE, null, ex.getMessage());
        }
        return null;
    }

    private static List<String> normalizeSentenceToToken(String sentence) {
        Token token = new Token(sentence);
        List<String> tokens = token.Tokenizer();
        return tokens;
    }

    private static String getQuery(String question) {
        List<String> tokens = normalizeSentenceToToken(question);
        String query = "[";
        for (String token : tokens) {
            query += token + ",";
        }
        query = query.substring(0, query.length() - 1) + "]";
        return query;
    }

    public static Node getDCGTree(String syntax) {
        Parser parser = new Parser();
        Node node = new Node();
        node = parser.ParseSentence(syntax);
        return node;

    }

    public static Node getNodeByTag(String tag, String syntax) {
        Stack<Node> stack = new Stack<Node>();
        Node root = getDCGTree(syntax);
        stack.add(root);
        while (!stack.empty()) {
            Node node = stack.pop();
            if (node.getValue().equals(tag)) {
                return node;
            }
            List<Node> nodes = node.getNodeChild();
            if (nodes != null) {
                boolean addAll = stack.addAll(nodes);
            }
        }
        return null;
    }

    public static String getPatternAnswer(String syntax) {
        String pattern = "";
        List<String> leafNodes = new ArrayList<String>();
        Stack<Node> stack = new Stack<Node>();
        Node root = getDCGTree(syntax);
        stack.add(root);
        while (!stack.empty()) {
            Node node = stack.pop();
            String nodeValue = node.getValue();
            if (nodeValue.equals("tu_nghi_van")) {
                leafNodes.add("{qa}");
            } else {
                List<Node> nodes = node.getNodeChild();
                if (nodes != null) {
                    stack.addAll(nodes);
                } else {
                    if (!nodeValue.equals("?")) {
                        if (nodeValue.equals("con_vật") || nodeValue.equals("loài")) {
                            leafNodes.add("con");

                        } else {
                            leafNodes.add(nodeValue.replace("_", " "));

                        }
                    }
                }
            }
        }
        for (int i = leafNodes.size() - 1; i >= 0; i--) {
            pattern += leafNodes.get(i) + " ";
        }

        return pattern;
    }

    public static String getPatternAnswerTypeFour(String syntax) {
        String pattern = "";
        List<String> leafNodes = new ArrayList<String>();
        Stack<Node> stack = new Stack<Node>();
        Node root = getDCGTree(syntax);
        stack.add(root);
        while (!stack.empty()) {
            Node node = stack.pop();

            if (!node.getValue().contains("tu_nghi_van")) {
                List<Node> nodes = node.getNodeChild();
                if (nodes != null) {
                    stack.addAll(nodes);
                } else {
                    if (!node.getValue().equals("?")) {
                        if (!node.getNodeParent().getValue().equals("gia_tri_hanh_dong")
                                && !node.getNodeParent().getValue().equals("gia_tri_thuoc_tinh")) {
                            leafNodes.add(node.getValue().replace("_", " "));
                        } else {
                            leafNodes.add("{qa}");
                        }
                    }

                }
            }
        }
        for (int i = leafNodes.size() - 1; i >= 0; i--) {
            pattern += leafNodes.get(i) + " ";
        }

        return pattern;
    }

    public static String getSyntaxName(String sentence) throws SAXException {
        List<String> syntaxFiles = LoadConfig();
        String strQuery = getQuery(sentence);
        strQuery = "cau_hoi(" + strQuery + ",[])";
        Query query = null;
        Query queryQuestion = null;

        for (String syntax : syntaxFiles) {
            query = new Query("consult('Grammars/" + syntax + "')");
            if (query.hasSolution()) {

                queryQuestion = new Query(strQuery);
                if (queryQuestion.hasSolution()) {
                    return syntax;
                }
            }
        }
        return null;
    }

    public static String loadSyntaxFile(String sentence) throws SAXException {
        String fileName = getSyntaxName(sentence);
        if (fileName != null) {
            //load syntax file
            String strQuery = getQuery(sentence);
            strQuery = "cau_hoi(X," + strQuery + ",[])";
            Query query = new Query("consult('Grammars/" + fileName + "_Syntax')");
            if (query.hasSolution()) {
                Query queryQuestion = new Query(strQuery);
                return queryQuestion.oneSolution().get("X").toString();
            }

        }
        return null;

    }

    public static String loadSemanticFile(String sentence) throws SAXException {
        String fileName = getSyntaxName(sentence);
        if (fileName != null) {
            //load syntax file
            String strQuery = getQuery(sentence);
            strQuery = "cau_hoi(X," + strQuery + ",[])";
            Query query = new Query("consult('Grammars/" + fileName + "_Semantic')");
            if (query.hasSolution()) {
                Query queryQuestion = new Query(strQuery);
                return queryQuestion.oneSolution().get("X").toString();
            }

        }
        return null;
    }

    public static List<String> loadBrainFile(String semantic, String type) throws ParserConfigurationException, SAXException, IOException {
        //load brain file
        semantic = semantic.replace(" ", "");
        List<String> result = new ArrayList<String>();
        String predicate = findPredicateName(semantic);
        type = findTypeQuestion(type);
        try {
            JPL.init();

            if (type.equals("1") || type.equals("2")) {
                String strQuery = "evaluate(" + semantic + ",X," + predicate + ")";
                Query query = new Query("reconsult('Brain/qasystem')");
                if (query.hasSolution()) {
                    Query queryQuestion = new Query(strQuery);
                    Hashtable[] allSolutions = queryQuestion.allSolutions();
                    for (Hashtable solution : allSolutions) {
                        String answer = solution.get("X").toString();
                        if (answer.contains("__"))
                        {
                            answer = answer.replace("__",",");
                        }
                        result.add(answer.replace("_", " "));
                    }
                }
            } else if (type.equals("3")) {
                String strQuery = "evaluatecount(" + semantic + ",X," + predicate + ")";
                Query query = new Query("reconsult('Brain/qasystem-count')");
                if (query.hasSolution()) {
                    Query queryQuestion = new Query(strQuery);
                    if (queryQuestion.hasSolution()) {
                        String answer = queryQuestion.oneSolution().get("X").toString();
                        result.add(answer);
                    }

                }
            } else if (type.equals("4")) {
                String strQuery = "evaluatetruefalse(" + semantic + "," + predicate + ")";
                Query query = new Query("reconsult('Brain/qasystem-truefalse')");
                if (query.hasSolution()) {
                    Query queryQuestion = new Query(strQuery);
                    if (queryQuestion.hasSolution()) {
                        result.add("đúng");
                    } else {
                        result.add("sai");
                    }
                }
            }
        } catch (JPLException ex) {
            JOptionPane.showMessageDialog(null, ex.getMessage());
        }
        return result;
    }

    private static String findPredicateName(String semantic) {
        int beginIndex = semantic.indexOf(",");
        int endIndex = semantic.indexOf("(", beginIndex);
        String predicate = semantic.substring(beginIndex + 1, endIndex);
        return predicate;
    }

    public static String findTypeQuestion(String type) {
        int beginIndex = type.indexOf("_");
        type = type.substring(beginIndex + 1, beginIndex + 2);
        return type;
    }

    public static List<String> generateAnswer(String pattern, List<String> answers) {
        List<String> result = new ArrayList<String>();
        String sentence = "";
        for (String answer : answers) {
            sentence = pattern.replace("{qa}", answer);
            result.add(sentence);
        }

        return result;
    }

    public static List<String> answer(String semantic, List<String> result) {
        if (result.get(0).equals("sai")) {
            String predicate = findPredicateName(semantic);
            int beginIndex = semantic.indexOf(",", semantic.indexOf(",") + 1);
            int endIndex = semantic.indexOf(")");
            semantic = semantic.replace(semantic.substring(beginIndex + 1, endIndex), "X");
            String strQuery = "evaluate(" + semantic + ",X," + predicate + ")";
            Query query = new Query("reconsult('Brain/qasystem')");
            if (query.hasSolution()) {
                Query queryQuestion = new Query(strQuery);
                Hashtable[] allSolutions = queryQuestion.allSolutions();
                for (Hashtable solution : allSolutions) {
                    String answer = solution.get("X").toString();
                    result.add(answer.replace("_", " "));
                }
            }
        }
        return result;
    }

    public static GraphViz generateDotLanguage(String syntax) {
        GraphViz gv = new GraphViz();
        Node root = getDCGTree(syntax);
        StringBuilder result = new StringBuilder();
        Stack<Node> stack = new Stack<Node>();
        stack.add(root);
        gv.addln(gv.start_graph());
        gv.addln("node [color=lightblue2, style=filled];");
        while (!stack.empty()) {
            Node node = stack.pop();
            List<Node> children = node.getNodeChild();
            if (children != null) {
                for (Node child : children) {
                    if (child.getValue().equals("?")) {
                        result.append("\"").append(node.getValue()).append("\"" + "->" + "\"?\"");
                        result.append("\"").append(node.getValue()).append("\"" + "[shape=box]");

                    } else {
                        if (node.getNodeChild() != null) {
                            result.append("\"").append(node.getValue()).append("\"" + "[shape=box]");
                        }
                        if (node.getValue().equals("doi_tuong_nghi_van")) {
                            if (child.getValue().equals("con")) {
                                result.append("\"").append(node.getValue()).append("\"" + "->" + "\"").append(child.getValue()).append(" " + "\"" + ";");
                            } else {
                                result.append("\"").append(node.getValue()).append("\"" + "->" + "\"").append(child.getValue().replace("_", " ")).append("\"" + ";");
                            }
                        } else {
                            if (child.getNodeChild() != null) {
                                result.append("\"").append(node.getValue()).append("\"" + "->" + "\"").append(child.getValue()).append("\"" + ";");
                            } else {
                                result.append("\"").append(node.getValue()).append("\"" + "->" + "\"").append(child.getValue().replace("_", " ")).append("\"" + ";");

                            }
                        }
                    }
                }
                stack.addAll(children);
            }
        }
        gv.addln(result.toString());
        gv.addln(gv.end_graph());
        return gv;
    }

    public static Image generateGraph(GraphViz gv) {
        Image image = Toolkit.getDefaultToolkit().createImage(gv.getGraph(gv.getDotSource(), "png"));
        return image;
    }
}
